package health_system.health_system.service;



import health_system.health_system.dto.FriendshipDTO;
import health_system.health_system.dto.FriendshipUpdateDTO;
import health_system.health_system.dto.PageResponseDTO;
import health_system.health_system.dto.UserDTO;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Optional;

/**
 * Service interface for managing friendships
 */
public interface FriendshipService {

    /**
     * Create a new friendship request
     * 
     * @param friendshipDTO the friendship data
     * @return the created friendship DTO
     */
    FriendshipDTO createFriendship(FriendshipDTO friendshipDTO);
    
    /**
     * Accept a friendship request
     * 
     * @param id the friendship id
     * @return the updated friendship DTO
     */
    FriendshipDTO acceptFriendship(Long id);
    
    /**
     * Reject a friendship request
     * 
     * @param id the friendship id
     * @return the updated friendship DTO
     */
    FriendshipDTO rejectFriendship(Long id);
    
    /**
     * Delete a friendship
     * 
     * @param id the friendship id
     */
    void deleteFriendship(Long id);
    
    /**
     * Get all friends for a user (as UserDTOs)
     * 
     * @param userId the user id
     * @return list of user DTOs
     */
    List<UserDTO> getFriendsByUser(Long userId);
    
    /**
     * Get pending friend requests received by a user
     * 
     * @param userId the user id
     * @return list of friendship DTOs
     */
    List<FriendshipDTO> getPendingFriendRequests(Long userId);
    
    /**
     * Get friend requests sent by a user
     * 
     * @param userId the user id
     * @return list of friendship DTOs
     */
    List<FriendshipDTO> getSentFriendRequestsByUser(Long userId);
    
    /**
     * Get a friendship by id
     * 
     * @param id the friendship id
     * @return the friendship DTO
     */
    FriendshipDTO getFriendshipById(Long id);
    
    /**
     * Find the friendship between two users
     * 
     * @param userId1 first user id
     * @param userId2 second user id
     * @return the optional friendship DTO if exists
     */
    Optional<FriendshipDTO> findFriendshipBetweenUsers(Long userId1, Long userId2);
    
    /**
     * Check if two users are friends
     * 
     * @param userId1 first user id
     * @param userId2 second user id
     * @return true if users are friends, false otherwise
     */
    boolean areFriends(Long userId1, Long userId2);
    
    /**
     * Block a user (either from an existing friendship or creating a new one)
     * 
     * @param userId the user doing the blocking
     * @param targetUserId the user to block
     * @return the updated or new friendship DTO
     */
    FriendshipDTO blockUser(Long userId, Long targetUserId);
    
    /**
     * Unblock a previously blocked user
     * 
     * @param userId the user doing the unblocking
     * @param targetUserId the user to unblock
     * @return the updated friendship DTO
     */
    FriendshipDTO unblockUser(Long userId, Long targetUserId);
    
    /**
     * Update friendship details (notes, circle)
     * 
     * @param id the friendship id
     * @param updateDTO the friendship update data
     * @param userId the user id making the update (must be involved in the friendship)
     * @return the updated friendship DTO
     */
    FriendshipDTO updateFriendship(Long id, FriendshipUpdateDTO updateDTO, Long userId);
    
    /**
     * Get all friendships for a user (any status)
     * 
     * @param userId the user id
     * @return list of friendship DTOs
     */
    List<FriendshipDTO> getAllFriendshipsByUser(Long userId);
    
    /**
     * Get all accepted friendships for a user
     * 
     * @param userId the user id
     * @return list of friendship DTOs
     */
    List<FriendshipDTO> getAcceptedFriendshipsByUser(Long userId);
    
    /**
     * Get paginated list of accepted friendships for a user
     * 
     * @param userId the user id
     * @param pageable pagination information
     * @return paginated friendship DTOs
     */
    PageResponseDTO<FriendshipDTO> getAcceptedFriendshipsByUser(Long userId, Pageable pageable);
    
    /**
     * Get blocked relationships for a user
     * 
     * @param userId the user id
     * @return list of friendship DTOs
     */
    List<FriendshipDTO> getBlockedRelationshipsByUser(Long userId);
    
    /**
     * Get friendships by friend circle
     * 
     * @param userId the user id
     * @param circleName the friend circle name
     * @return list of friendship DTOs
     */
    List<FriendshipDTO> getFriendshipsByCircle(Long userId, String circleName);
    
    /**
     * Get friends by friend circle
     * 
     * @param userId the user id
     * @param circleName the friend circle name
     * @return list of user DTOs
     */
    List<UserDTO> getFriendsByCircle(Long userId, String circleName);
    
    /**
     * Get all friend circles for a user
     * 
     * @param userId the user id
     * @return list of circle names
     */
    List<String> getAllFriendCirclesByUser(Long userId);
    
    /**
     * Count friends for a user
     * 
     * @param userId the user id
     * @return count of friends
     */
    Long countFriendsByUser(Long userId);
    
    /**
     * Count friends in a circle
     * 
     * @param userId the user id
     * @param circleName the friend circle name
     * @return count of friends in the circle
     */
    Long countFriendsInCircle(Long userId, String circleName);
    
    /**
     * Update friend circle for a friendship
     * 
     * @param id the friendship id
     * @param userId the user id making the update (must be involved in the friendship)
     * @param circleName the new circle name
     * @return the updated friendship DTO
     */
    FriendshipDTO updateFriendCircle(Long id, Long userId, String circleName);
    
    /**
     * Search friends by name
     * 
     * @param userId the user id
     * @param searchTerm the search term
     * @return list of user DTOs
     */
    List<UserDTO> searchFriendsByName(Long userId, String searchTerm);
    
    /**
     * Find possible mutual friends (friends of friends who are not direct friends)
     * 
     * @param userId the user id
     * @return list of user DTOs
     */
    List<UserDTO> findPossibleMutualFriends(Long userId);
} 